iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 23
0
Modern Web

從零開始進入 JavaScript & TypeScript 的世界系列 第 23

第 23 天-好用的柯里化(Currying)

  • 分享至 

  • xImage
  •  

使用 Currying 就像還貸款一樣,可以慢慢還,不用一口氣還完。也就是說,呼叫函式時,不用一次給足所有的參數,可以一個一個慢慢給。

記得第一次使用到這個技巧的時候是在寫 Scala 的時候,當時一開始不太理解為何要這樣用,但用了一陣子之後就發現這個 Currying 實在是相當好用,因為它可以簡化參數的處理過程,大大的提高了程式碼的彈性、可測試性和可讀性。

舉個例子來說,假設我有一個函式必須要傳入三個參數,第一個是 instance,第二個是 url,第三個是其他參數。那麼我們每次在使用這個函式時就必須得帶入這三個參數,使用起來就會有那麼一點不太方便。這時候我們就可以使用 Currying 將這個函式帶入第一個參數 instance 得到 函式1,那麼我就可以重複利用 函式1 來操作,每次只要帶入兩個參數即可。

又假設,如果我們的 URL 又是相同的,我們就可以將 函式1 帶入 URL 這個參數並且得到 函式2,那我們又可以重複使用 函式2 並帶入不同的其他參數來使用。這樣一來對於冗長的程式碼、需要客製化的 函式 處理有很大的幫助。

在 JavaScript 寫起來可能會有點複雜,但是在 TypeScript 裡寫起來就簡單需多,他的語法是:

let function_name = (param1:type) => (param2:type) => ... => (paramN) => {
  // process param and return result
}

以剛剛描述中的例子可以寫成這樣:

let queryData = (connection: string) => (url: string) =>
    (method: string) => (parameter: string) => {
        console.log("Use Connection: " + connection +
            ", connect to " + url +
            " with method " + method +
            " and parameter:" + parameter);
    }

let a = queryData("SuperConnection");
let b = a("MY_URL");
let c = b("GET");

c("data=123");
c("data=456");

queryData 如果改用 JavaScript 寫就會像這樣,也就是除非給到最後一個參數,不然每次都是會回傳一個新的函式加上我們給的參數。

var queryData = function(connection) {
    return function(url) {
        return function(method) {
            return function(parameter) {
                console.log("Use Connection: " + connection +
                    ", connect to " + url +
                    " with method " + method +
                    " and parameter:" + parameter);
            };
        };
    };
};

執行上面那段範例後,會有這樣的結果:

Use Connection: SuperConnection, connect to MY_URL with method GET and parameter:data=123
Use Connection: SuperConnection, connect to MY_URL with method GET and parameter:data=456

這樣我們在重複使用 c 的時候不就是簡潔很多呢!


上一篇
第22天-Literal Types(字面上的型別)
下一篇
第 24 天-提高程式碼品質的樣板字串(Template String)
系列文
從零開始進入 JavaScript & TypeScript 的世界30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言